/* eslint-disable no-new-func */
/* eslint-disable prefer-promise-reject-errors */
/* eslint-disable no-cond-assign */
/**
 * @description:  自动创建文件
 * @param {type}
 */
let fs = require('fs')
let path = require('path')
const entryConfig = require('./pagesSetting') // 生成入口文件对象

class Task {
  /**
   * 自动创建路由目录的任务
   * @param {String} moduleName 模块名称
   * @param {Object} moduleConfig 模块设置
   * @param {String} moduleConfig.entry 模块入口路径
   */
  constructor(moduleName, moduleConfig, args) {
    this.createProcedure = args._[1] || 'views'
    this.moduleName = moduleName
    this.moduleConfig = moduleConfig
    this.routerPath = path.resolve(this.moduleConfig.entry, `../${this.createProcedure}`)
  }

  run () {
    this.getRouterFile(async text => {
      let parse = new Function('return ' + text)
      let router = parse()

      for (const route of router.routes) {
        this.parseRoute(route)
      }
    })
  }

  /**
   * 解析路由，自动生成目录以及代码文件
   * @param {Object} route 路由配置
   * @param {String} route.path 路由路径
   * @param {Array} route.children 子路由
   */
  async parseRoute (route) {
    // 保证目录创建
    await this.createDir(route.path)
    // 如果有子路由，就递归处理
    // 如果没有子路由，就需要创建代码文件
    if (route.children) {
      for (const subRoute of route.children) {
        this.parseRoute(subRoute)
      }
    } else {
      this.createBasicFiles(route.path, route.type)
    }
  }

  /**
   * 根据entry路径，获取路由文件
   */
  getRouterFile (callback) {
    let routerPath = path.resolve(__dirname, this.moduleConfig.entry, '../router/index.js')
    fs.readFile(routerPath, 'utf8', (err, data) => {
      if (err) {
        console.log(`模块${this.moduleName}没有找到路由文件，请确定路径是否为"./router/index.js"`)
        return
      }
      let text = this.parseRouterFile(data)
      callback(text)
    })
  }

  /**
   * 解析router文件的文本
   * @param {String} text
   */
  parseRouterFile (text) {
    let startIndex = text.indexOf('{')
    let endIndex = text.lastIndexOf('}')
    let router = text.substring(startIndex, endIndex + 1)
    // 移除component这个选项，因为这里可能用到的是变量会导致解析失败
    router = router.replace(/component: .*\n/g, '')
    return router
  }

  /**
   * 根据路由Path创建对应的文件夹目录
   * @param {String} routePath
   * @returns {Promise}
   */
  createDir (routePath) {
    if (routePath === '*') return

    let targetPath = path.resolve(this.routerPath, '.' + routePath)
    return new Promise((resolve, reject) => {
      fs.access(targetPath, err => {
        if (err) {
          fs.mkdir(targetPath, { recursive: true }, (err) => {
            if (err) {
              console.log(`目录${targetPath}创建失败`, err)
              reject()
            } else {
              console.log(`目录${targetPath}创建成功`)
              resolve()
            }
          })
        } else {
          console.log('目录已存在', targetPath)
          resolve()
        }
      })
    })
  }
  // 创建基础模板
  setBase (createFile, dirPath) {
    createFile('index.less', '')
    createFile('index.vue',
      `<template>
  <div>${dirPath}/index.vue</div>
</template>
<script>
  export default {
    data () {
      return {}
    }
  }
</script>
<style lang="less" scoped>
@import "./index.less";
</style>`
    )
  }
  /**
   * 在创建完目录之后，在该目录下创建一些基本的文件
   */
  createBasicFiles (dir, type) {
    let dirPath = path.resolve(this.routerPath, '.' + dir)
    let createFile = (name, content) => {
      let filePath = path.resolve(dirPath, './' + name)
      fs.access(filePath, err => {
        if (err) {
          fs.writeFile(filePath, content, err => {
            if (err) return
            console.log(`成功创建${filePath}文件`)
          })
        } else {
          console.log('文件已存在', filePath)
        }
      })
    }
    fs.readdir(dirPath, (err, files) => {
      if (err) return
      try {
        var file = fs.readdirSync(`example/${type}`)
        // 如果不指定模板或者模板不存在，则创建空模板
        if (!type) {
          this.setBase(createFile, dirPath)
          return
        }
        file.map(i => {
          var HTML = fs.readFileSync(`example/${type}/` + i, 'utf-8')
          createFile(i, HTML)
        })
      } catch (error) {
        this.setBase(createFile, dirPath)
      }
    })
  }
}
module.exports = (api, projectOptions) => {
  api.registerCommand('setPages', {
    description: '根据路由json自动生成相应目录',
    usage: 'vue-cli-service setPages',
    options: {}
  }, async function serve (args) {
    /*
    npm run setPages mode file（单页面不支持mode和file）
    mode: 需要生成的模块
    file: 生成文件夹名称
    */
    // 模块目录
    const pages = entryConfig.discriminate()
    const prescribedRoute = args._[0]
    if (prescribedRoute) {
      let task = new Task(prescribedRoute, pages[prescribedRoute], args)
      task.run()
      return
    }
    Object.entries(pages)
      .forEach(([name, config], index) => {
        let task = new Task(name, config, args)
        task.run()
      })
  })
}
